home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / INDENT3.ARJ / PARSE.C < prev    next >
Text File  |  1992-08-04  |  9KB  |  324 lines

  1. /* Copyright (c) 1980 Regents of the University of California. All rights
  2.  * reserved.  The Berkeley software License Agreement specifies the terms and
  3.  * conditions for redistribution. */
  4.  
  5. #ifndef lint
  6. static char sccsid[] = "@(#)parse.c     5.2 (Berkeley) 8/28/85";
  7. #endif not lint
  8.  
  9. /*-
  10.  *
  11.  *                        Copyright (C) 1976
  12.  *                              by the
  13.  *                        Board of Trustees
  14.  *                              of the
  15.  *                      University of Illinois
  16.  *
  17.  *                       All rights reserved
  18.  *
  19.  *
  20.  * FILE NAME:
  21.  *      parse.c
  22.  *
  23.  * PURPOSE:
  24.  *      Contains the routines which keep track of the parse stack.
  25.  *
  26.  * GLOBALS:
  27.  *      ps.p_stack =    The parse stack, set by both routines
  28.  *      ps.il =         Stack of indentation levels, set by parse
  29.  *      ps.cstk =               Stack of case statement indentation levels, set by parse
  30.  *      ps.tos =                Pointer to top of stack, set by both routines.
  31.  *
  32.  * FUNCTIONS:
  33.  *      parse
  34.  *      reduce
  35.  */
  36. /*-
  37.  * Copyright (C) 1976 by the Board of Trustees of the University of Illinois 
  38.  *
  39.  * All rights reserved 
  40.  *
  41.  *
  42.  * NAME: parse 
  43.  *
  44.  * FUNCTION: Parse is given one input which is a "maxi token" just scanned
  45.  * from input.  Maxi tokens are signifigant constructs such as else, {,
  46.  * do, if (...), etc.  Parse works with reduce to maintain a parse stack
  47.  * of these constructs.  Parse is responsible for the "shift" portion of
  48.  * the parse algorithm, and reduce handles the "reduce" portion. 
  49.  *
  50.  * HISTORY: initial coding      November 1976   D A Willcox of CAC 
  51.  *
  52.  */
  53.  
  54. #include "indent_globs.h"
  55.  
  56. void parse(tk)
  57.     int tk;            /* the code for the construct scanned */
  58. {
  59.     int i;
  60.  
  61. #ifdef debug
  62.     printf("%2d - %s\n", tk, token);
  63. #endif
  64.     while (ps.p_stack[ps.tos] == ifhead && tk != elselit) {
  65.     /* true if we have an if without an else */
  66.     ps.p_stack[ps.tos] = stmt;    /* apply the if(..) stmt ::= stmt
  67.                      * reduction */
  68.     reduce();        /* see if this allows any reduction */
  69.     }
  70.  
  71.  
  72.     switch (tk) {        /* go on and figure out what to do with the
  73.                  * input */
  74.  
  75.     case decl:        /* scanned a declaration word */
  76.         ps.search_brace = btype_2;
  77.         /* indicate that following brace should be on same line */
  78.         if (ps.p_stack[ps.tos] != decl) {    /* only put one declaration
  79.                          * onto stack */
  80.         break_comma = true;    /* while in declaration, newline
  81.                      * should be forced after comma */
  82.         ps.p_stack[++ps.tos] = decl;
  83.         ps.il[ps.tos] = ps.i_l_follow;
  84.  
  85.         if (ps.ljust_decl) {    /* only do if we want left justified
  86.                      * declarations */
  87.             ps.ind_level = 0;
  88.             for (i = ps.tos - 1; i > 0; --i)
  89.             if (ps.p_stack[i] == decl)
  90.                 ++ps.ind_level;    /* indentation is number of
  91.                          * declaration levels deep we
  92.                          * are */
  93.             ps.i_l_follow = ps.ind_level;
  94.         }
  95.         }
  96.         break;
  97.  
  98.     case ifstmt:        /* scanned if (...) */
  99.         if (ps.p_stack[ps.tos] == elsehead && ps.else_if)    /* "else if ..." */
  100.         ps.i_l_follow = ps.il[ps.tos];
  101.     case dolit:        /* 'do' */
  102.     case forstmt:        /* for (...) */
  103.         ps.p_stack[++ps.tos] = tk;
  104.         ps.il[ps.tos] = ps.ind_level = ps.i_l_follow;
  105.         ++ps.i_l_follow;    /* subsequent statements should be indented 1 */
  106.         ps.search_brace = btype_2;
  107.         break;
  108.  
  109.     case lbrace:        /* scanned { */
  110.         break_comma = false;/* don't break comma in an initial list */
  111.         if (ps.p_stack[ps.tos] == stmt || ps.p_stack[ps.tos] == decl
  112.         || ps.p_stack[ps.tos] == stmtl)
  113.         ++ps.i_l_follow;/* it is a random, isolated stmt group or a
  114.                  * declaration */
  115.         else {
  116.         if (s_code == e_code) {
  117.             /* only do this if there is nothing on the line */
  118.             --ps.ind_level;
  119.             /* it is a group as part of a while, for, etc. */
  120.             if (ps.p_stack[ps.tos] == swstmt && ps.case_indent)
  121.             --ps.ind_level;
  122.             /* for a switch, brace should be two levels out from the
  123.              * code */
  124.         }
  125.         }
  126.  
  127.         ps.p_stack[++ps.tos] = lbrace;
  128.         ps.il[ps.tos] = ps.ind_level;
  129.         ps.p_stack[++ps.tos] = stmt;
  130.         /* allow null stmt between braces */
  131.         ps.il[ps.tos] = ps.i_l_follow;
  132.         break;
  133.  
  134.     case whilestmt:    /* scanned while (...) */
  135.         if (ps.p_stack[ps.tos] == dohead) {
  136.         /* it is matched with do stmt */
  137.         ps.ind_level = ps.i_l_follow = ps.il[ps.tos];
  138.         ps.p_stack[++ps.tos] = whilestmt;
  139.         ps.il[ps.tos] = ps.ind_level = ps.i_l_follow;
  140.         } else {        /* it is a while loop */
  141.         ps.p_stack[++ps.tos] = whilestmt;
  142.         ps.il[ps.tos] = ps.i_l_follow;
  143.         ++ps.i_l_follow;
  144.         ps.search_brace = btype_2;
  145.         }
  146.  
  147.         break;
  148.  
  149.     case elselit:        /* scanned an else */
  150.  
  151.         if (ps.p_stack[ps.tos] != ifhead)
  152.         diag(1, "Unmatched 'else'");
  153.         else {
  154.         ps.ind_level = ps.il[ps.tos];    /* indentation for else
  155.                          * should be same as for if */
  156.         ps.i_l_follow = ps.ind_level + 1;    /* everything following
  157.                              * should be in 1 level */
  158.         ps.p_stack[ps.tos] = elsehead;
  159.         /* remember if with else */
  160.         ps.search_brace = btype_2;
  161.         }
  162.  
  163.         break;
  164.  
  165.     case rbrace:        /* scanned a } */
  166.         /* stack should have <lbrace> <stmt> or <lbrace> <stmtl> */
  167.         if (ps.p_stack[ps.tos - 1] == lbrace) {
  168.         ps.ind_level = ps.i_l_follow = ps.il[--ps.tos];
  169.         ps.p_stack[ps.tos] = stmt;
  170.         } else
  171.         diag(1, "Stmt nesting error.");
  172.         break;
  173.  
  174.     case swstmt:        /* had switch (...) */
  175.         ps.p_stack[++ps.tos] = swstmt;
  176.         ps.cstk[ps.tos] = case_ind;
  177.         /* save current case indent level */
  178.         ps.il[ps.tos] = ps.i_l_follow;
  179.         case_ind = ps.i_l_follow + ps.case_indent;    /* cases should be one
  180.                              * level down from
  181.                              * switch */
  182.         ps.i_l_follow += ps.case_indent + 1;    /* statements should be
  183.                              * two levels in */
  184.         ps.search_brace = btype_2;
  185.         break;
  186.  
  187.     case semicolon:    /* this indicates a simple stmt */
  188.         break_comma = false;/* turn off flag to break after commas in a
  189.                  * declaration */
  190.         ps.p_stack[++ps.tos] = stmt;
  191.         ps.il[ps.tos] = ps.ind_level;
  192.         break;
  193.  
  194.     default:        /* this is an error */
  195.         diag(1, "Unknown code to parser");
  196.         return;
  197.  
  198.  
  199.     }                /* end of switch */
  200.  
  201.     reduce();            /* see if any reduction can be done */
  202. #ifdef debug
  203.     for (i = 1; i <= ps.tos; ++i)
  204.     printf("(%d %d)", ps.p_stack[i], ps.il[i]);
  205.     printf("\n");
  206. #endif
  207.     return;
  208. }
  209.  
  210. /*-
  211.  * Copyright (C) 1976 by the Board of Trustees of the University of Illinois 
  212.  *
  213.  * All rights reserved 
  214.  *
  215.  * NAME: reduce
  216.  *
  217.  * FUNCTION: Implements the reduce part of the parsing algorithm
  218.  *
  219.  * ALGORITHM: The following reductions are done.  Reductions are repeated
  220.  *      until no more are possible.
  221.  *
  222.  * Old TOS              New TOS
  223.  * <stmt> <stmt>        <stmtl>
  224.  * <stmtl> <stmt>       <stmtl>
  225.  * do <stmt>            "dostmt"
  226.  * if <stmt>            "ifstmt"
  227.  * switch <stmt>        <stmt>
  228.  * decl <stmt>          <stmt>
  229.  * "ifelse" <stmt>      <stmt>
  230.  * for <stmt>           <stmt>
  231.  * while <stmt>         <stmt>
  232.  * "dostmt" while       <stmt>
  233.  *
  234.  * On each reduction, parser_state_tos->i_l_follow
  235.  * (the indentation for the following line)
  236.  * is set to the indentation level associated with the old TOS.
  237.  *
  238.  * PARAMETERS: None
  239.  *
  240.  * RETURNS: Nothing
  241.  *
  242.  * GLOBALS: ps.cstk ps.i_l_follow = ps.il ps.p_stack = ps.tos = 
  243.  *
  244.  * CALLS: None 
  245.  *
  246.  * CALLED BY: parse 
  247.  *
  248.  * HISTORY: initial coding      November 1976   D A Willcox of CAC 
  249.  *
  250.  */
  251.  
  252. /*----------------------------------------------*\
  253.  |   REDUCTION PHASE
  254. \*----------------------------------------------*/
  255. void reduce()
  256. {
  257.     register int i;
  258.  
  259.     for (;;) {            /* keep looping until there is nothing left
  260.                  * to reduce */
  261.  
  262.     switch (ps.p_stack[ps.tos]) {
  263.  
  264.         case stmt:
  265.         switch (ps.p_stack[ps.tos - 1]) {
  266.  
  267.             case stmt:
  268.             case stmtl:
  269.             /* stmtl stmt or stmt stmt */
  270.             ps.p_stack[--ps.tos] = stmtl;
  271.             break;
  272.  
  273.             case dolit:/* <do> <stmt> */
  274.             ps.p_stack[--ps.tos] = dohead;
  275.             ps.i_l_follow = ps.il[ps.tos];
  276.             break;
  277.  
  278.             case ifstmt:
  279.             /* <if> <stmt> */
  280.             ps.p_stack[--ps.tos] = ifhead;
  281.             for (i = ps.tos - 1; (ps.p_stack[i] != stmt && ps.p_stack[i] != stmtl && ps.p_stack[i] != lbrace); --i);
  282.             ps.i_l_follow = ps.il[i];
  283.             /* for the time being, we will assume that there is
  284.              * no else on this if, and set the indentation level
  285.              * accordingly. If an else is scanned, it will be
  286.              * fixed up later */
  287.             break;
  288.  
  289.             case swstmt:
  290.             /* <switch> <stmt> */
  291.             case_ind = ps.cstk[ps.tos - 1];
  292.  
  293.             case decl:    /* finish of a declaration */
  294.             case elsehead:
  295.             /* <<if> <stmt> else> <stmt> */
  296.             case forstmt:
  297.             /* <for> <stmt> */
  298.             case whilestmt:
  299.             /* <while> <stmt> */
  300.             ps.p_stack[--ps.tos] = stmt;
  301.             ps.i_l_follow = ps.il[ps.tos];
  302.             break;
  303.  
  304.             default:    /* <anything else> <stmt> */
  305.             return;
  306.  
  307.         }        /* end of section for <stmt> on top of stack */
  308.         break;
  309.  
  310.         case whilestmt:    /* while (...) on top */
  311.         if (ps.p_stack[ps.tos - 1] == dohead) {
  312.             /* it is termination of a do while */
  313.             ps.p_stack[--ps.tos] = stmt;
  314.             break;
  315.         } else
  316.             return;
  317.  
  318.         default:        /* anything else on top */
  319.         return;
  320.  
  321.     }
  322.     }
  323. }
  324.